package com.g0dkar.leet.util.ognl;

import java.util.Map;

import net.vidageek.mirror.exception.MirrorException;
import ognl.NullHandler;
import ognl.ObjectNullHandler;

import com.g0dkar.leet.util.ognl.typeConversion.TypeConverter;
import com.g0dkar.leet.util.ognl.typeConversion.TypeConverterManager;
import com.g0dkar.leet.util.reflection.ReflectionUtils;

/**
 * A custom OGNL {@link NullHandler} for JHeat. It creates new instances of null objects using a
 * {@link TypeConverter#newInstance(Class)} method or {@link ReflectionUtils#newInstance(Class, Object...)} if no
 * {@link TypeConverter} can be found.
 * 
 * @author Rafael g0dkar Lins
 * 
 */
public class LeetOGNLNullHandler extends ObjectNullHandler {
	public Object nullPropertyValue(Map context, Object target, Object property) {
		if ((target == null) || (property == null)) {
			return null;
		}
		
		try {
			String propName = property.toString();
			ReflectionUtils.Field field = ReflectionUtils.getField(propName, target.getClass());
			Object obj = null;
			
			if (field != null) {
				obj = newInstanceFromConverter(field);
			}
			else {
				obj = ReflectionUtils.newInstance(ReflectionUtils.findField(propName, target.getClass()).getType());
			}
			
			if (obj != null) {
				OgnlUtils.set(propName, obj, target);
			}
			
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private Object newInstanceFromConverter(ReflectionUtils.Field field) {
		TypeConverter converter = TypeConverterManager.getConverterFor(field.type);
		
		if (converter != null) {
			try {
				return converter.newInstance(field.type);
			} catch (Exception e) {
				try {
					return ReflectionUtils.newInstance(field.type);
				} catch (MirrorException me) {
					return null;
				}
			}
		}
		else {
			try {
				return ReflectionUtils.newInstance(field.type);
			} catch (MirrorException me) {
				return null;
			}
		}
	}
}
